Założyłem takie współczynniki korelacji między inwestycjami: r12 = 0.2, r13 = 0.15, r23 = 0.4, ufność na poziomie 99.9%, liczbę scenariuszy o liczbie równej 30000.
library(mvtnorm)
library(dplyr)
library(stats)
library(DT)
#Funcja służąca przypisania do wylosowanej liczby danego ratingu. Operacja jest wykonywana dla każdej firmy. Argumentem funkcji jest ramka danych z wylosowanych liczb z wielowymiarowego rozkładu normalnego, ratingi początkowe oraz macierz przejścia.
matchranking <- function(losowanie, oceny, ratings){
ramka <- data.frame(matrix(data = NA, nrow = nrow(losowanie), ncol = (length(oceny)*2)))
for (i in 1:length(oceny)){
letters <- c()
ratingfun <- ratings[oceny[i],]
dystr <- dystrybuanta(ratingfun)
dystrkw <- kwant(dystr)
for(a in 1:nrow(losowanie)){
for(b in 1:ncol(dystrkw)){
if((losowanie[a,i] >= dystrkw[5,b]) & (losowanie[a,i] < dystrkw[4,b])){
letters <- c(letters, colnames(dystrkw)[b])
break
}
}
}
ramka[,i] <- losowanie[,i]
ramka[,length(oceny)+i] <- letters
}
return(ramka)
}
# Funkcja licząca dystrybuantę, jako argument przyjmuję wartości z macierzy przejścia (określony rząd)
dystrybuanta <- function(wartosci) {
dol <- c(0)
gora <- c(wartosci[,length(wartosci)])
for(i in 2:(length(wartosci))){
gora <- c(gora, gora[(i-1)] + wartosci[, (length(wartosci)-i+1)])
dol <- c(dol, gora[i-1])
}
data <- t(data.frame(rev(as.vector(gora)),rev(as.vector(dol))))
colnames(data) <- colnames(wartosci)
rownames(data) <- c("Gora", "Dol")
dyst <- rbind(wartosci, data)
return(dyst)
}
#Funkcja obliczająca kwantyle rozkładu normalnegi dla danych wejściowych.
kwant <- function(dystr){
dane <- as.data.frame(sapply(dystr[c(2,3),],qnorm, mean=0, sd=1))
return(rbind(dystr,dane))
}
#Funkcja obliczająca wycenę dla wszystkich obligacji, argumentem jest ramka danych scenariuszy, stopy zwrotu, stopy odzysku, wektor lat, wartości ceny wykupu, wartości kuponów, typ obligacji oraz argument typu bool świadczący o tym, czy losuję wartość procentową ile dostanie pożyczkodawca gdyby firma zbankrutowała
wycena_wszystkich_obligacji <- function(scenarios, tab_proc, default_table, lata, wartosci, kupony, typ, los=F){
scenarios <- scenarios[,((ncol(scenarios)/2)+1):ncol(scenarios)]
for(i in 1:nrow(scenarios)){
for(j in 1:(ncol(scenarios))){
rating <- scenarios[i,j]
if(rating=="Def"){
scenarios[i,j] <- round(wycena_obligacji_bankrut(default_table, wartosci[j], typ = typ[j], los = los),2)
} else{
scenarios[i,j] <- round(wycena_jednej_obligacji(tab_proc, kupon = kupony[j], wartosc = wartosci[j], lata = lata[j], rating),2)
}
}
}
for(k in 1:ncol(scenarios)){
scenarios[,k] <- as.numeric(scenarios[,k])
}
return(scenarios)
}
#Funkcja licząca wartość jednej obligacji. Argumenty: Stopy zwrotu, kupon, wartość ceny wykupu, lata, rating firmy
wycena_jednej_obligacji <- function(stzwrotu, kupon, wartosc, lata, rat){
wart<- 0
if(kupon!=0){
wart<- kupon
}
for(i in 1:(lata-1)){
wart<- wart+ kupon/(1+(stzwrotu[rat,i]/100))^i
}
wart<- wart + wartosc/(1+(stzwrotu[rat, (lata-1)]/100))^(lata-1)
return(wart)
}
#Funkcja licząca wartość jednej obligacji, gdy firma zbankrutuje. Argumenty: Stopy odzysku, wartość ceny wykupu, typ obligacji oraz czy losuję wartość, jaką pożyczkodawca dostanie spowrotem.
wycena_obligacji_bankrut <- function(default_tabelka, wartosc, typ, los = F){
tab <- default_tabelka[typ,]
if(los == F){
return((tab[,1]/100)*wartosc)
}
procent <- rnorm(n=1,mean = tab[,1], sd=tab[,2])/100
if(procent < 0){
return(0)
} else if (procent > 1){
return(wartosc)
} else{
return(wartosc*procent)
}
}
#Liczę wartość portfela na podstawie wycenionych obligacji. Argumentem jest ramka z wycenionymi obligacjami.
wartosc_portfela <- function(ramka){
portfel <- rowSums(ramka)
ramka <- cbind(ramka, portfel)
return(ramka)
}
#Liczę VaR o podanej ufności dla ramki zawierającej wartości porfeli.
count_var <- function(ramka, kwantyl){
ramka <- ramka %>% arrange(portfel)
wartosci <- as.vector(ramka[,ncol(ramka)])
return(as.numeric(quantile(wartosci, (1-kwantyl))))
}
#Liczę ES o podanej ufności dla ramki zawierającej wartości porfeli.
count_ES <- function(ramka, kwantyl){
ramka <- ramka %>% arrange(portfel)
wartosci <- as.vector(ramka[,ncol(ramka)])
indeks_do_wycięcia <- length(wartosci) * (1-kwantyl)
wyc_wartosci <- wartosci[1:indeks_do_wycięcia]
return(mean(wyc_wartosci))
}
#Szukam wartości portfela gdyby ratingi się nie zmieniły. Argumenty: scenariusze, ratingi początkowe, wartości portfeli.
znajdz_wycene_aktualna <- function(dataframe, ratingi, portfele){
dataframe <- dataframe[, (ncol(dataframe)-length(ratingi)+1):ncol(dataframe)]
for (i in 1:nrow(dataframe)) {
if (all(dataframe[i, ] == ratingi)) {
wycena <- portfele[i, ncol(portfele)]
return(wycena)
}
}
return(0)
}
#Główna funkcja licząca VaR i ES. Argumenty: współczynniki korelacji, liczba scenariuszy, ratingi początkowe, macierz przejścia, stopy zwrotu, stopy odzysku, wektory lat, cen wykupu, kuponów, typów obligacji, ufność oraz czy losuję wartość ze stopy odzysku w przypadku bankructwa firmy.
credit_metrics <- function(korelacje, scenariusze, ratingi_poczatkowe, dataratings,
data_stopy_zwrotu,
data_stopy_odzysku,
lata,
cena_wykupu,
kupony,
typ,
kwantyl,
los=F){
losowanie <- rmvnorm(scenariusze, mean = rep(0,nrow(korelacje)), sigma = korelacje)
scen <- matchranking(losowanie, ratingi_poczatkowe, dataratings)
wycena <- wycena_wszystkich_obligacji(scen,
data_stopy_zwrotu,
data_stopy_odzysku,
lata,
cena_wykupu,
kupony,
typ,
los=los)
wyceny_portfeli <- wartosc_portfela(wycena)
wycena_aktualnych_ratingow <- znajdz_wycene_aktualna(scen, ratingi_poczatkowe, wyceny_portfeli)
VaR <- wycena_aktualnych_ratingow - count_var(wyceny_portfeli, kwantyl)
ES <- wycena_aktualnych_ratingow - count_ES(wyceny_portfeli, kwantyl)
return(list("Scenariusze" = scen, "Wycena" = wyceny_portfeli, "VaR" = VaR, "ES" = ES))
}
stopy_zwrotu_df <- data.frame("Year 1" = c(3.60, 3.65, 3.72, 4.10, 5.55, 6.05, 15.05),
"Year 2" = c(4.17, 4.22, 4.32, 4.67, 6.02, 7.02, 15.02),
"Year 3" = c(4.73, 4.78, 4.93, 5.25, 6.78, 8.03, 14.03),
"Year 4" = c(5.12, 5.17, 5.32, 5.63, 7.27, 8.52, 13.52))
rownames(stopy_zwrotu_df) <- c("AAA", "AA", "A", "BBB", "BB", "B", "CCC")
stopy_odzysku_df <- data.frame(row.names = c("Senior Secured", "Senior Unsecured", "Senior Subordinated", "Subordinated", "Junior Subordninated"),
"Mean %" = c(53.80, 51.13, 38.52, 32.74, 17.09),
"Standard Deviation %" = c(26.86, 25.45, 23.81, 20.18, 10.90))
data_ratings_df <- read.csv2("Ratings.csv", row.names = 1)
korelacje <- matrix(c(1,0.2,0.15,
0.2,1,0.4,
0.15,0.4,1), nrow=3)
var_z_korelacja <- credit_metrics(korelacje = korelacje,
scenariusze = 30000,
ratingi_poczatkowe = c("A", "B", "CCC"),
dataratings = data_ratings_df,
data_stopy_zwrotu = stopy_zwrotu_df,
data_stopy_odzysku = stopy_odzysku_df,
lata = c(3,5,2),
cena_wykupu = c(100000, 50000, 50000),
kupony = c(0,5000,10000),
typ = c("Subordinated", "Senior Secured", "Senior Unsecured"),
kwantyl = 0.999,
los=F)
korelacje <- matrix(c(1,0,0,
0,1,0,
0,0,1), nrow=3)
var_bez_korelacji<-credit_metrics(korelacje = korelacje,
scenariusze = 30000,
ratingi_poczatkowe = c("A", "B", "CCC"),
dataratings = data_ratings_df,
data_stopy_zwrotu = stopy_zwrotu_df,
data_stopy_odzysku = stopy_odzysku_df,
lata = c(3,5,2),
cena_wykupu = c(100000, 50000, 50000),
kupony = c(0,5000,10000),
typ = c("Subordinated", "Senior Secured", "Senior Unsecured"),
kwantyl = 0.999)
datatable(var_bez_korelacji$Scenariusze)
datatable(var_bez_korelacji$Wycena)
VaRiES <- data.frame("VaR"=c(var_bez_korelacji$VaR, var_z_korelacja$VaR), "ES"=c(var_bez_korelacji$ES, var_z_korelacja$ES), row.names = c("Bez korelacji", "Z korelacjami"))
datatable(VaRiES)
var_z_korelacja_los <- credit_metrics(korelacje = korelacje,
scenariusze = 30000,
ratingi_poczatkowe = c("A", "B", "CCC"),
dataratings = data_ratings_df,
data_stopy_zwrotu = stopy_zwrotu_df,
data_stopy_odzysku = stopy_odzysku_df,
lata = c(3,5,2),
cena_wykupu = c(100000, 50000, 50000),
kupony = c(0,5000,10000),
typ = c("Subordinated", "Senior Secured", "Senior Unsecured"),
kwantyl = 0.999,
los=T)
korelacje <- matrix(c(1,0,0,
0,1,0,
0,0,1), nrow=3)
var_bez_korelacji_los<-credit_metrics(korelacje = korelacje,
scenariusze = 30000,
ratingi_poczatkowe = c("A", "B", "CCC"),
dataratings = data_ratings_df,
data_stopy_zwrotu = stopy_zwrotu_df,
data_stopy_odzysku = stopy_odzysku_df,
lata = c(3,5,2),
cena_wykupu = c(100000, 50000, 50000),
kupony = c(0,5000,10000),
typ = c("Subordinated", "Senior Secured", "Senior Unsecured"),
kwantyl = 0.999,
los=T)
VaRiESLOS <- data.frame("VaR"=c(var_bez_korelacji_los$VaR, var_z_korelacja_los$VaR), "ES"=c(var_bez_korelacji_los$ES, var_z_korelacja_los$ES), row.names = c("Bez korelacji", "Z korelacjami"))
datatable(VaRiESLOS)